SPORE.$Import('core.object');
SPORE.$Import('core.browser');

/*
---

name: Event

description: Contains the Event Class, to make the event object cross-browser.

license: MIT-style license.

requires: [Window, Document, Array, Function, String, Object]

provides: Event

...
*/

SPORE.register('core.event',function($ns){

	var Event = this.Event = new Type('Event', function(event, win){
		if (!win) win = window;
		var doc = win.document;
		event = event || win.event;
		if (event.$extended) return event;
		this.$extended = true;
		var type = event.type,
			target = event.target || event.srcElement,
			page = {},
			client = {},
			related = null,
			rightClick, wheel, code, key;
		while (target && target.nodeType == 3) target = target.parentNode;
	
		if (type.indexOf('key') != -1){
			code = event.which || event.keyCode;
			key = Object.keyOf(Event.Keys, code);
			if (type == 'keydown'){
				var fKey = code - 111;
				if (fKey > 0 && fKey < 13) key = 'f' + fKey;
			}
			if (!key) key = String.fromCharCode(code).toLowerCase();
		} else if ((/click|mouse|menu/i).test(type)){
			doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
			page = {
				x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
				y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
			};
			client = {
				x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
				y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
			};
			if ((/DOMMouseScroll|mousewheel/).test(type)){
				wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
			}
			rightClick = (event.which == 3) || (event.button == 2);
			if ((/over|out/).test(type)){
				related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
				var testRelated = function(){
					while (related && related.nodeType == 3) related = related.parentNode;
					return true;
				};
				var hasRelated = (Browser.firefox2) ? testRelated.attempt() : testRelated();
				related = (hasRelated) ? related : null;
			}
		} else if ((/gesture|touch/i).test(type)){
			this.rotation = event.rotation;
			this.scale = event.scale;
			this.targetTouches = event.targetTouches;
			this.changedTouches = event.changedTouches;
			var touches = this.touches = event.touches;
			if (touches && touches[0]){
				var touch = touches[0];
				page = {x: touch.pageX, y: touch.pageY};
				client = {x: touch.clientX, y: touch.clientY};
			}
		}
	
		return Object.append(this, {
			event: event,
			type: type,
	
			page: page,
			client: client,
			rightClick: rightClick,
	
			wheel: wheel,
	
			relatedTarget: document.id(related),
			target: document.id(target),
	
			code: code,
			key: key,
	
			shift: event.shiftKey,
			control: event.ctrlKey,
			alt: event.altKey,
			meta: event.metaKey
		});
	});
	
	Event.Keys = {
		'enter': 13,
		'up': 38,
		'down': 40,
		'left': 37,
		'right': 39,
		'esc': 27,
		'space': 32,
		'backspace': 8,
		'tab': 9,
		'delete': 46
	};
	
	
	
	Event.implement({
	
		stop: function(){
			return this.stopPropagation().preventDefault();
		},
	
		stopPropagation: function(){
			if (this.event.stopPropagation) this.event.stopPropagation();
			else this.event.cancelBubble = true;
			return this;
		},
	
		preventDefault: function(){
			if (this.event.preventDefault) this.event.preventDefault();
			else this.event.returnValue = false;
			return this;
		}
	
	});

});